iT邦幫忙

2021 iThome 鐵人賽

DAY 17
1
Modern Web

Canvas 小錦囊系列 第 17

Day 17 - canvas 文字換行

  • 分享至 

  • xImage
  •  

程式碼

今天來學習文字換行

export default function App() {
  const canvasRef = useRef(null);
  useEffect(() => {
    if (canvasRef?.current) {
      const canvas = canvasRef?.current;
      const ctx = canvas.getContext("2d");
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.fillStyle = "gray";
      ctx.font = "30px Arial";
      ctx.lineWidth = 1;
      const str =
        "來到第十七篇了囉!鐵人賽真的好辛苦!!神人們真的太神了~~~~";
      ctx.fillText(str, 0, 50);
    }
  }, [canvasRef]);

  return (
    <div className="App">
      <canvas
        ref={canvasRef}
        id="canvas"
        style={{ border: "solid 1px blue" }}
        width="300"
        height="300"
      ></canvas>
    </div>
  );
}

在一般填上文字的時候,是無法自己換行的,需要進行運算才可以達到完整顯示文字的效果。

  /*
str:要繪製的字串
canvas:canvas物件
initX:繪製字串起始x座標
initY:繪製字串起始y座標
lineHeight:字行高,自己定義個值即可
*/
  const canvasTextAutoLine = (str, canvas, initX, initY, lineHeight) => {
    var ctx = canvas.getContext("2d");
    var lineWidth = 0;
    var canvasWidth = canvas.width;
    var lastSubStrIndex = 0;
    for (let i = 0; i < str.length; i++) {
      lineWidth += ctx.measureText(str[i]).width;
      if (lineWidth > canvasWidth - initX) {
        //減去initX,防止邊界出現的問題
        ctx.fillText(str.substring(lastSubStrIndex, i), initX, initY);
        initY += lineHeight;
        lineWidth = 0;
        lastSubStrIndex = i;
      }
      if (i === str.length - 1) {
        ctx.fillText(str.substring(lastSubStrIndex, i + 1), initX, initY);
      }
    }
  };

把剛才的 fillText 替換成 canvasTextAutoLine,從程式碼可以發現,我們使用寬度與文字去計算,超過就進行換行,來達到效果。

完成啦~~~

完整程式碼 codesandbox

碎碎念時間

/images/emoticon/emoticon13.gif
前兩篇因為時間的關係,給自己太難得題目,白天又忙得不可開交,造成無法做出成果,如果未來幾天還有時間會回頭補上... ,不知不覺已經過了二分之一的賽程了,再接再厲!


上一篇
Day 16 - 用 canvas 做射擊小遊戲
下一篇
Day 18 - 用 canvas 製作電子賀卡
系列文
Canvas 小錦囊30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言